package ${servicePackageName}.service.sys.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import ${commonPackageName}.constant.Constant;
import ${commonPackageName}.enums.ExceptionEnum;
import ${commonPackageName}.exception.BusinessException;
import ${commonPackageName}.utils.AssertUtil;
import ${commonPackageName}.utils.RedisUtil;
import ${servicePackageName}.dto.ResourceRoleTreeParentDto;
import ${servicePackageName}.dto.sys.LoginDto;
import ${servicePackageName}.dto.sys.UserDto;
import ${servicePackageName}.entity.sys.SysUser;
import ${servicePackageName}.mapstruct.SysUserConverMapper;
import ${servicePackageName}.qo.sys.LoginReq;
import ${servicePackageName}.service.sys.AuthSerivce;
import ${servicePackageName}.service.sys.ISysResourceService;
import ${servicePackageName}.service.sys.ISysUserDepartmentService;
import ${servicePackageName}.service.sys.ISysUserService;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;

/**
 * 登录service实现类
 * @author lizihao
 *
 */
@Service
public class AuthServiceImpl implements AuthSerivce{

	@Autowired
	private ISysUserService iUserService;
	@Autowired
	private ISysResourceService iResourceService;
	@Autowired
	private ISysUserDepartmentService iSysUserDepartmentService;
    @Autowired
    private RedisUtil redisUtil;
	
    /**
     * 登录service
     */
	@Override
	public LoginDto login(LoginReq loginReq) throws Exception{
		String redisVerifyCode = (String) redisUtil.get(loginReq.getCaptchaKey());
		AssertUtil.isNull(redisVerifyCode, () -> new BusinessException(ExceptionEnum.VERIFY_GUOQI));
		AssertUtil.isTrue(!loginReq.getCaptcha().toLowerCase().equals(redisVerifyCode.toLowerCase()),() -> new BusinessException(ExceptionEnum.VERIFY_ERROR));
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_account", loginReq.getUserAccount());
        SysUser u = iUserService.getOne(queryWrapper);
        AssertUtil.isNull(u, () -> new BusinessException(ExceptionEnum.ACCOUNT_OR_PASSWORD_ERROR));
        AssertUtil.isTrue(!SecureUtil.md5(loginReq.getUserPassword().concat(u.getUserSalt())).equals(u.getUserPassword()), 
        		() -> new BusinessException(ExceptionEnum.ACCOUNT_OR_PASSWORD_ERROR));
       String token =  IdUtil.randomUUID();
       //多个角色的要去重路由
       List<ResourceRoleTreeParentDto> resourceList = iResourceService.selectUserResourceList(u.getId());
       //获取用户所在部门列表
       List<Long> departmentList = iSysUserDepartmentService.getUserDepatmentList(u.getId());
       
       //返回给前端的
       LoginDto dto = assembleUser(u, token, resourceList, Convert.toList(String.class, departmentList));
       //删除验证码
       redisUtil.del(loginReq.getCaptchaKey());
		return dto;
	}

	
	/**
	 * 组装用户dto 
	 * @param u
	 * @param token
	 * @param resourceList
	 * @param departmentList
	 * @return
	 */
	private LoginDto assembleUser(SysUser u, String token, List<ResourceRoleTreeParentDto> resourceList,
			List<String> departmentList) {
			LoginDto dto = new LoginDto().setToken(token).setResourceList(resourceList);
		   //系统内部封装的用户信息
		   UserDto userDto = SysUserConverMapper.INSTANCES.sysUserToUserDto(u);
		   List<String> permissionList = new ArrayList<String>();
		   getNodes(permissionList, resourceList);
		   userDto.setResourceList(resourceList).setToken(token).setPermissionList(permissionList).setDepartmentList(departmentList);
		   redisUtil.set(token, userDto, Constant.TOKEN_TIME_OUT);
		return dto;
	}
	
	/**
	 * 递归获取所有父子节点
	 * @param permissionList
	 * @param resourceList
	 */
	private void getNodes(List<String> permissionList, List<ResourceRoleTreeParentDto> resourceList) {
		for(ResourceRoleTreeParentDto d : resourceList) {
			permissionList.add(d.getResourceCode());
			if(d.getChildren().size()!=0) {
				getNodes(permissionList, d.getChildren());
			}
		}
	}
}
